package cn.neusoft.controller;

import cn.neusoft.domain.CargoDeployBill;
import cn.neusoft.domain.CargoDescription;
import cn.neusoft.domain.DeployBillStageEnum;
import cn.neusoft.service.CargoAndDescriptionService;
import cn.neusoft.service.DepBillService;
import cn.neusoft.service.DispatchService;
import cn.neusoft.tool.PageSet;
import cn.neusoft.vo.ResultBean;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/depBill")
public class DepBillController {

    @Autowired
    private DepBillService depBillService;
    @Autowired
    private CargoAndDescriptionService cargoAndDescriptionService;
    @Autowired
    private DispatchService dispatchService;
    @PostMapping("/generateDepBill")
    public synchronized ResultBean  generateDepBill(@RequestBody Map<String, Object> map){
        ResultBean resultBean;

        if(map != null){
            try{
                String warehouseName = (String) map.get("warehouseName");
                String missionID = (String) map.get("missionID") ;
                DeployBillStageEnum stage = DeployBillStageEnum.valueOf((String) map.get("stage"));
                if(stage != DeployBillStageEnum.PRE_IN && stage != DeployBillStageEnum.PRE_OUT){
                    return ResultBean.error(1, "类型错误");
                }
                java.sql.Date date = new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse((String) map.get("date")).getTime());

                List<Map<String, String>> list = (List<Map<String, String>>) (map.get("cargoInf"));

                Map<String, Double> planCargosInf = new HashMap<>();
                Map<String, Double> realCargosInf = new HashMap<>();
                for(Map<String, String> m : list){

                    if(planCargosInf.get(m.get("cargoName")) != null){
                        planCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("planQuantities")) + planCargosInf.get(m.get("cargoName")));
                    }
                    else{
                        planCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("planQuantities")));

                    }
                    realCargosInf.put(m.get("cargoName"), 0.0);
                }

                CargoDeployBill cargoDeployBill = new CargoDeployBill(planCargosInf, realCargosInf, date, Integer.parseInt(missionID), warehouseName, stage);
                int reply = depBillService.generateDepBill(cargoDeployBill);
                switch(reply){
                    case 1:
                        resultBean = ResultBean.success();
                        break;
                    case 0:
                        resultBean = ResultBean.error(7021, "失败");
                        break;
                    case -3:
                        resultBean = ResultBean.error(7022, "存在商品描述未设置最大上限");
                        break;
                    case -4:
                        resultBean = ResultBean.error(7023, "存在进货商品超过库房最大上限");
                        break;
                    default:
                        resultBean = ResultBean.error(7024, "未知错误");
                        break;
                }
            }catch (Exception e){
                e.printStackTrace();
                resultBean = ResultBean.error(7025, "错误");

            }

        }
        else{
            resultBean = ResultBean.error(7020, "输入为空");
        }

        return resultBean;
    }
    @PostMapping("/changeDepBill")
    @ApiOperation("stage不允许更改")
    public synchronized ResultBean changeDepBill(@RequestBody HashMap<String, Object> map){
      ResultBean resultBean;

      if(map != null){
        try{
            int id = (int) map.get("id");
            CargoDeployBill find = depBillService.getDepBillByID(id);
            if(find != null){
                String warehouseName = (String) map.get("warehouseName");
                String missionID = (String) map.get("missionID");
                DeployBillStageEnum stage = DeployBillStageEnum.valueOf((String) map.get("stage"));
                if(stage != find.getStage()){
                    return ResultBean.error(1, "不允许更改状态");
                }
                java.sql.Date date = new java.sql.Date(new SimpleDateFormat("yyyy-MM-dd").parse((String) map.get("date")).getTime());

                List<Map<String, String>> list = (List<Map<String, String>>) (map.get("cargoInf"));

                Map<String, Double> planCargosInf = new HashMap<>();
                Map<String, Double> realCargosInf = new HashMap<>();
                for(Map<String, String> m : list){

                    if(planCargosInf.get(m.get("cargoName")) != null){
                        planCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("planQuantities")) + planCargosInf.get(m.get("cargoName")));
                    }
                    else{
                        planCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("planQuantities")));

                    }
                    if(realCargosInf.get(m.get("cargoName")) != null){
                        realCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("realQuantities")) + realCargosInf.get(m.get("cargoName")));
                    }
                    else{
                        realCargosInf.put(m.get("cargoName"), Double.valueOf(m.get("realQuantities")));

                    }
                }

                int reply = depBillService.revertDepBill(find);
                if(reply > 0){
                    find.setPlanCargosInf(planCargosInf);
                    find.setRealCargosInf(realCargosInf);
                    find.setDate(date);
                    find.setMissionID(Integer.parseInt(missionID));
                    find.setAimWarehouseName(warehouseName);
                    find.setStage(stage);
                }
                switch(find.getStage()){
                    case PRE_OUT:
                    case PRE_IN:
                        boolean isPer = depBillService.isPermittedCreate(find);
                        if(isPer){
                            reply = depBillService.changeDepBill(find);
                            if(reply > 0){
                                reply = dispatchService.applyDepBill(find.getId());
                            }
                        }
                        break;
                    default:
                        reply = depBillService.changeDepBill(find);
                        break;
                }

                switch(reply){
                    case 1:
                        resultBean = ResultBean.success();
                        break;
                    case 0:
                        resultBean = ResultBean.error(7021, "失败");
                        break;
                    case -3:
                        resultBean = ResultBean.error(7022, "存在商品描述未设置最大上限");
                        break;
                    case -4:
                        resultBean = ResultBean.error(7023, "存在进货商品超过库房最大上限");
                        break;
                    default:
                        resultBean = ResultBean.error(7024, "未知错误");
                        break;
                }
            }
            else{
                resultBean = ResultBean.error(7024, "未知错误");

            }

        }catch (Exception e){
          e.printStackTrace();
          resultBean = ResultBean.error(7025, "错误");

        }

      }
      else{
        resultBean = ResultBean.error(7020, "输入为空");
      }

      return resultBean;
    }
    @PostMapping("/queryDepBill")
    @ApiOperation("若日期为空，则默认对应界不限日期")
    public synchronized ResultBean queryDepBill(Map<String, Object> map){
        ResultBean resultBean = null;

        if(map != null){
            if(map.containsKey("stage") && map.containsKey("from") && map.containsKey("to")){
                DeployBillStageEnum stage = (DeployBillStageEnum) map.get("stage");
                Date from = (Date) map.get("from");
                Date to = (Date) map.get("to");

                if(stage != null && from != null && to != null){
                    List<CargoDeployBill> list = depBillService.queryDepBill(stage, from, to);
                    resultBean = ResultBean.success(list);
                }
                else{
                    resultBean = ResultBean.error(7040, "输入为空");
                }
            }
            else{
                resultBean = ResultBean.error(7042, "输入为空");
            }
        }
        else{
            resultBean = ResultBean.error(7041, "输入为空");

        }




        return resultBean;
    }
    @GetMapping("/deleteDepBill/{id}")
    public synchronized ResultBean deleteDepBill(@PathVariable("id") int id){
        ResultBean resultBean = null;

        CargoDeployBill cargoDeployBill = depBillService.getDepBillByID(id);
        if(cargoDeployBill != null){
            int reply = depBillService.revertDepBill(cargoDeployBill);
            if(reply > 0){
                if(depBillService.deleteDepBill(id) > 0){
                    resultBean = ResultBean.success();

                }
                else{
                    resultBean = ResultBean.error(7050, "错误");

                }
            }
            else{
                resultBean = ResultBean.error(7050, "错误");

            }
        }
        else{
            resultBean = ResultBean.error(7050, "错误");

        }



        return resultBean;
    }

    @PostMapping("/getAllDepPage")
    public synchronized ResultBean getAllDepPage(@RequestBody Map<String, String> map){
        ResultBean resultBean;

        List<CargoDepBillReturn> ans = new ArrayList<CargoDepBillReturn>();


        try{
            int pageNum = Integer.parseInt(map.get("pageNum"));
            int pageSize = Integer.parseInt(map.get("pageSize"));
            Date from =  null;
            Date to = null;
            if(!map.get("from").equals("")){
                from = new SimpleDateFormat("yyyy-MM-dd").parse(map.get("from"));
            }
            if(!map.get("to").equals("")){
                to = new SimpleDateFormat("yyyy-MM-dd").parse(map.get("to"));
            }
            DeployBillStageEnum stage = null;
            String stageStr = map.get("stage");
            if(stageStr.equals("")){
                stage = DeployBillStageEnum.ALL;
            }
            else{
                stage = DeployBillStageEnum.valueOf(stageStr);
            }

            List<CargoDeployBill> list = depBillService.queryDepBill(stage, from, to);

            for(CargoDeployBill c : list){
                List<DepTableElement> line = new ArrayList<>();
                Map<String, Double> realMap = c.getRealCargosInf();
                for(Map.Entry<String, Double> entry : c.getPlanCargosInf().entrySet()){
                    double realQuantities;
                    if(realMap.get(entry.getKey()) != null){
                        realQuantities = realMap.get(entry.getKey());
                    }
                    else{
                        realQuantities = 0;
                    }
                    CargoDescription cargoDescription = cargoAndDescriptionService.getByDesName(entry.getKey());
                    DepTableElement depTableElement;
                    if(cargoDescription != null){
                        depTableElement = new DepTableElement(entry.getKey(), Integer.toString(cargoDescription.getId()),
                                cargoDescription.getUnit(), Double.toString(entry.getValue()), Double.toString(realQuantities));
                    }
                    else{
                        depTableElement = new DepTableElement(entry.getKey(), "未设置商品",
                                "未设置商品", Double.toString(entry.getValue()), Double.toString(realQuantities));
                    }
                    line.add(depTableElement);

                }
                CargoDepBillReturn cargoDepBillReturn = new CargoDepBillReturn(c.getId(), c.getDate(), Integer.toString(c.getMissionID()), line, c.getStage(), c.getAimWarehouseName());
                ans.add(cargoDepBillReturn);
            }


            PageSet<CargoDepBillReturn> pageSet = new PageSet<CargoDepBillReturn>(ans, pageSize);
            Map<String, Object> answer = new HashMap<>();
            answer.put("total", pageSet.getTotal());
            answer.put("list", pageSet.getPage(pageNum));

            resultBean = ResultBean.success(answer);

        }catch(Exception e){
            e.printStackTrace();
            resultBean = ResultBean.error(1, "错误");
        }

        return resultBean;
    }

    @PostMapping("/changeStageDepBill")
    public synchronized ResultBean changeStageDepBill(@RequestBody Map<String, String> map){
        ResultBean resultBean = null;

        if(map != null){
            int id = Integer.parseInt(map.get("id"));
            DeployBillStageEnum stageEnum = DeployBillStageEnum.valueOf(map.get("stage"));

            CargoDeployBill cargoDeployBill = depBillService.getDepBillByID(id);
            if(cargoDeployBill != null){
                int ans = depBillService.stageChangeDepBill(cargoDeployBill, stageEnum);
                if(ans > 0){
                    resultBean = ResultBean.success();
                }
                else{
                    resultBean = ResultBean.error(1, "失败");
                }
            }
        }

        return resultBean;
    }

    private class CargoDepBillReturn {
        private int id;
        private Date date;
        private String missionID;
        private List<DepTableElement> list;
        private DeployBillStageEnum stage;
        private String warehouseName;

        public CargoDepBillReturn(int id, Date date, String missionID, List<DepTableElement> list, DeployBillStageEnum stage, String warehouseName) {
            this.id = id;
            this.date = date;
            this.missionID = missionID;
            this.list = list;
            this.stage = stage;
            this.warehouseName = warehouseName;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            this.date = date;
        }

        public String getMissionID() {
            return missionID;
        }

        public void setMissionID(String missionID) {
            this.missionID = missionID;
        }

        public List<DepTableElement> getList() {
            return list;
        }

        public void setList(List<DepTableElement> list) {
            this.list = list;
        }

        public DeployBillStageEnum getStage() {
            return stage;
        }

        public void setStage(DeployBillStageEnum stage) {
            this.stage = stage;
        }

        public String getWarehouseName() {
            return warehouseName;
        }

        public void setWarehouseName(String warehouseName) {
            this.warehouseName = warehouseName;
        }
    }

    private class DepTableElement {
        private String cargoName;
        private String id;
        private String unit;
        private String planQuantities;
        private String realQuantities;


        public DepTableElement(String cargoName, String id, String unit, String planQuantities, String realQuantities) {
            this.cargoName = cargoName;
            this.id = id;
            this.unit = unit;
            this.planQuantities = planQuantities;
            this.realQuantities = realQuantities;
        }

        public String getCargoName() {
            return cargoName;
        }

        public void setCargoName(String cargoName) {
            this.cargoName = cargoName;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getUnit() {
            return unit;
        }

        public void setUnit(String unit) {
            this.unit = unit;
        }

        public String getPlanQuantities() {
            return planQuantities;
        }

        public void setPlanQuantities(String planQuantities) {
            this.planQuantities = planQuantities;
        }

        public String getRealQuantities() {
            return realQuantities;
        }

        public void setRealQuantities(String realQuantities) {
            this.realQuantities = realQuantities;
        }
    }
}
